package com.example.klinedemo.play

import android.media.MediaCodec
import android.media.MediaFormat
import android.view.Surface
import java.io.File

class H264Player1(
    var path: File,// 解码器
    val surface: Surface
) : Runnable {

    var mediaCodec: MediaCodec

    init {
        // 初始化解码器
        mediaCodec = MediaCodec.createDecoderByType("video/avc")
        val mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480)
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 15)
        mediaCodec.configure(mediaFormat, surface, null, 0)
    }

    fun play() {
        mediaCodec.start()
        Thread(this).start()
    }

    override fun run() {
        try {
            h264Player()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun h264Player() {
        val bytes = getBytes(path)
        // 寻找空闲的容器的index
        val index = mediaCodec.dequeueInputBuffer(10000)

        // 获取到之后往里写数据
        var startIndex = 0;
        val bufferInfo = MediaCodec.BufferInfo() // 封装了帧的信息
        while (true) {
            // 拿到找到下一帧的起始位置
            val nexStart = findByFrame(bytes, startIndex + 2, bytes.size)
            if (nexStart == -1) {
                break
            }
            // 获取空闲的容器
            val inputBuffer = mediaCodec.getInputBuffer(index)
            // 按照帧的大小往里丢数据
            val length = nexStart - startIndex
            inputBuffer?.put(bytes, startIndex, length)
            // 将数据传给dsp解码 ，index代表是第几个容器有数据
            mediaCodec.queueInputBuffer(index, 0, length, 0, 0)

            // 开始输出
            mediaCodec.dequeueOutputBuffer(bufferInfo, 10000).apply {
                if (this >= 0) {
                    // 容器利用完毕了，需要释放容器
                    // 第二个参数传递true 直接会渲染到 surface中
                    mediaCodec.releaseOutputBuffer(this, true)
                }
            }
            startIndex += length
        }
    }

    private fun findByFrame(bytes: ByteArray, start: Int, size: Int): Int {
        for (i in start..size - 4) {
            if ((bytes[i] == 0x00.toByte() && bytes[i + 1] == 0x00.toByte()
                        && bytes[i + 2] == 0x00.toByte() && bytes[i + 3] == 0x01.toByte()) ||
                (bytes[i] == 0x00.toByte() && bytes[i + 1] == 0x00.toByte()
                        && bytes[i + 2] == 0x01.toByte())
            ) {
                return i
            }
        }
        return -1
    }

    private fun getBytes(path: File): ByteArray {
        val file = File("your/file/path")
        return file.readBytes() // 最简单的方式
    }


}